package br.gov.ms.tce.modelo.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import br.gov.ms.tce.modelo.dao.GenericDAO;

@Named
public abstract class GenericDAOJPA<T, ID extends Serializable> implements GenericDAO<T,ID> {

	 	private Class<T> persistentClass;
	 	
	 	/**
	 	 * Objeto de gerenciamento de peristência
	 	 */
	 	@PersistenceContext
	 	protected EntityManager entityManager;

		protected CriteriaBuilder cb;

		protected CriteriaQuery<T> query;

		protected Root<T> root;

	 	/**
	 	 * Construtor Padrão
	 	 */
	 	@SuppressWarnings("unchecked")
	    public GenericDAOJPA() {
	        this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
	                                .getGenericSuperclass()).getActualTypeArguments()[0];
	    }

	 
	    /**
	     * Retorna a classe persistente
	     * @return 
	     */
	    public Class<T> getPersistentClass() {
	        return persistentClass;
	    }

	    /**
	     * @see br.gov.ms.tce.modelo.dao.GenericDAO#loadById(java.io.Serializable)
	     */
	    public T loadById(ID id) {
	       return entityManager.find(persistentClass, id);
	    }

	    /**
	     * @see br.gov.ms.tce.modelo.dao.GenericDAO#persist(java.lang.Object)
	     */
	    public void persist(T entity) {
	        entityManager.persist(entity);
	    }
	    
	    /**
	     * @see br.gov.ms.tce.modelo.dao.GenericDAO#update(java.lang.Object)
	     */
	    public void update(T entity) {
	        entityManager.merge(entity);
	    }
	    
	    public void delete(T entity) {
	        entityManager.remove(entity);
	    }
	    
	    /**
	     * @see br.gov.ms.tce.modelo.dao.GenericDAO#loadAll()
	     */
	    @SuppressWarnings("unchecked")
	    public List<T> loadAll() {
	        return entityManager.createQuery("Select t from " + persistentClass.getSimpleName() + " t").getResultList();
	    }
	    
	    /**
	     * @see br.gov.ms.tce.modelo.dao.GenericDAO#loadAll(java.lang.String)
	     */
	    @SuppressWarnings("unchecked")
	    public List<T> loadAll(String order) {
	    	order = order!= null && !order.equals("") ? " order by t."+order:"";
	        return entityManager.createQuery("Select t from " + persistentClass.getSimpleName() + " t"+order).getResultList();
	    }
	    
	    /**
	     * @see br.gov.ms.tce.modelo.dao.GenericDAO#createCriteria()
	     */
	    public void createCriteria() {
			this.cb = this.entityManager.getCriteriaBuilder();
			this.query = cb.createQuery(persistentClass);
			this.root = query.from(persistentClass);
		}
	    
	    public List<T> getResultList(){
			TypedQuery<T> result = this.entityManager.createQuery(query);				
	    	return result.getResultList();
	    }	
}
